package com.one.blocks.security.authc.smscode;


import com.one.blocks.security.authc.AbstractAuthenticationProvider;
import com.one.blocks.security.enums.SecurityExceptionEnum;
import com.one.blocks.security.exception.AuthcException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;

/**
 * @author <a href="mailto:idler41@163.con">linfuxin</a> created on 2023-08-26 15:49:30
 */
@Slf4j
public class SmsCodeAuthenticationProvider extends AbstractAuthenticationProvider {

    private final SmsCodeService smsCodeService;

    public SmsCodeAuthenticationProvider(SmsCodeService smsCodeService) {
        super(null, null);
        this.smsCodeService = smsCodeService;
    }

    public SmsCodeAuthenticationProvider(SmsCodeService smsCodeService, UserDetailsChecker preAuthenticationChecks, UserDetailsChecker postAuthenticationChecks) {
        super(preAuthenticationChecks, postAuthenticationChecks);
        this.smsCodeService = smsCodeService;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    protected UserDetails retrieveUser(Authentication authentication) {
        return smsCodeService.loadByMobile((String) authentication.getPrincipal());
    }

    @Override
    protected Authentication buildSuccessAuthentication(Authentication authentication, UserDetails userDetails) {
        authentication.setAuthenticated(true);
        ((SmsCodeAuthenticationToken) authentication).setDetails(userDetails);
        return authentication;
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, Authentication authentication) {
        final String smsCode = (String) authentication.getCredentials();
        if (smsCode == null) {
            if (log.isDebugEnabled()) {
                log.debug("Authentication failed: no credentials provided");
            }
            throw new AuthcException(SecurityExceptionEnum.NO_SMS_CODE);
        }
        if (!smsCodeService.verifyCode(smsCode)) {
            throw new AuthcException(SecurityExceptionEnum.BAD_SMS_CODE);
        }
    }
}
